From: Keir Fraser Date: Wed, 10 Sep 2008 10:09:08 +0000 (+0100) Subject: CPUIDLE: Avoid remnant HPET intr while force hpetbroadcast X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14111^2~12 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=e862b83e8433d8b898b09079dacbffb3bd42af9f;p=xen.git CPUIDLE: Avoid remnant HPET intr while force hpetbroadcast Exit from C3 is mainly caused by HPET intr if force enable hpetbroadcast. But it is still probably caused by other unexpected events. In this case the HPET timer may still be alive while there is no CPU in C3. Avoid those remnant HPET intr can save cpu handling time and increase idle time. Signed-off-by: Wei Gang --- diff --git a/xen/arch/x86/hpet.c b/xen/arch/x86/hpet.c index 147705d2f0..31028cc2a6 100644 --- a/xen/arch/x86/hpet.c +++ b/xen/arch/x86/hpet.c @@ -100,6 +100,13 @@ static int reprogram_hpet_evt_channel( ch->next_event = expire; + if ( expire == STIME_MAX ) + { + /* We assume it will take a long time for the timer to wrap. */ + hpet_write32(0, HPET_T0_CMP); + return 0; + } + delta = min_t(int64_t, delta, MAX_DELTA_NS); delta = max_t(int64_t, delta, MIN_DELTA_NS); delta = ns2ticks(delta, ch->shift, ch->mult); @@ -206,10 +213,10 @@ void hpet_broadcast_enter(void) { struct hpet_event_channel *ch = &hpet_event; - cpu_set(smp_processor_id(), ch->cpumask); - spin_lock(&ch->lock); + cpu_set(smp_processor_id(), ch->cpumask); + /* reprogram if current cpu expire time is nearer */ if ( this_cpu(timer_deadline) < ch->next_event ) reprogram_hpet_evt_channel(ch, this_cpu(timer_deadline), NOW(), 1); @@ -222,8 +229,17 @@ void hpet_broadcast_exit(void) struct hpet_event_channel *ch = &hpet_event; int cpu = smp_processor_id(); + spin_lock_irq(&ch->lock); + if ( cpu_test_and_clear(cpu, ch->cpumask) ) + { reprogram_timer(per_cpu(timer_deadline, cpu)); + + if ( cpus_empty(ch->cpumask) && ch->next_event != STIME_MAX ) + reprogram_hpet_evt_channel(ch, STIME_MAX, 0, 0); + } + + spin_unlock_irq(&ch->lock); } int hpet_broadcast_is_available(void)